package io.renren.common.jackson;

import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * bean对象序列化规则
 *
 * @author 40659
 * @since 2025/2/14 13:41
 */
public class MyBeanSerializerModifier extends BeanSerializerModifier {

    /**
     * 更改每个bean的序列化属性
     */
    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
        //循环所有的beanProperties
        for (BeanPropertyWriter writer : beanProperties) {
            //给writer注册一个自己的nullSerializer
            if (isArrayType(writer)) {
                //这里使用单例的原因是每个被序列化的bean都要执行一次这个方法,且这个类里面的方法是线程安全的,如果每次都new,想想就挺可怕的
                writer.assignNullSerializer(NullArrayJsonSerializer.INSTANCE);
            } else if (isMapType(writer)) {
                writer.assignNullSerializer(NullMapJsonSerializer.INSTANCE);
            } else if (isBooleanType(writer)) {
                writer.assignNullSerializer(NullBooleanJsonSerializer.INSTANCE);
            } else if (isStringType(writer)) {
                writer.assignNullSerializer(NullObjectJsonSerializer.INSTANCE);
            }
        }

        return beanProperties;
    }


    /**
     * 是否是数组
     */
    private boolean isArrayType(BeanPropertyWriter writer) {
        Class<?> rawClass = writer.getType().getRawClass();
        return rawClass.isArray() || Collection.class.isAssignableFrom(rawClass);
    }

    /**
     * 是否是map
     */
    private boolean isMapType(BeanPropertyWriter writer) {
        Class<?> rawClass = writer.getType().getRawClass();
        return Map.class.isAssignableFrom(rawClass);
    }

    /**
     * 是否是boolean
     */
    private boolean isBooleanType(BeanPropertyWriter writer) {
        Class<?> rawClass = writer.getType().getRawClass();
        return Boolean.class.isAssignableFrom(rawClass);
    }

    /**
     * 是否是string
     */
    private boolean isStringType(BeanPropertyWriter writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return CharSequence.class.isAssignableFrom(clazz) || Character.class.isAssignableFrom(clazz);
    }
}
